<template>
	<div class="j-upload-file" :class="{ disabled: disabled || !isShowUpIcon }">
		<el-upload
			:action="action || PORT1 + '/sys/oss/upload'"
			:multiple="multiple"
			:on-preview="handlePreview"
			:on-remove="handleRemove"
			:before-remove="beforeRemove"
			:limit="limit"
			:accept="accept"
			v-model:file-list="formParam[column.prop]"
			:headers="headers"
			:data="data"
			:disabled="disabled"
			:before-upload="beforeUpload"
			:on-success="handleSuccess"
			:method="method"
			:listType="listType"
			:on-exceed="handleExceed"
		>
			<el-button type="primary" v-if="listType === 'text'">点击上传</el-button>
			<el-icon v-if="listType !== 'text'"><Plus /></el-icon>
			<template #tip v-if="!disabled && uploadTip">
				<div class="el-upload__tip">{{ uploadTip }}</div>
			</template>
		</el-upload>
		<el-dialog v-model="dialogVisible" title="查看图片">
			<img w-full :src="dialogImageUrl" alt="Preview Image" />
		</el-dialog>
	</div>
</template>

<script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus';
import type { UploadProps } from 'element-plus';
import { FromBoxProps } from '@/components/FormBox/interface';
import { GlobalStore } from '@/stores';
import { PORT1 } from '@/api/config/servicePort';
import { ref } from 'vue';
type FileTypes =
	| 'image/apng'
	| 'image/bmp'
	| 'image/gif'
	| 'image/jpeg'
	| 'image/pjpeg'
	| 'image/jpg'
	| 'image/png'
	| 'image/*'
	| 'image/svg+xml'
	| 'image/tiff'
	| 'image/webp'
	| 'image/x-icon'
	| '.docx'
	| '.doc'
	| '.txt'
	| '.xls'
	| '.xlsx'
	| '.ppt'
	| '.zip'
	| '.rar'
	| '.bmp'
	| '.rtf'
	| '.word';

interface Upload {
	listType?: string; // 文件列表的类型 'text' | 'picture' | 'picture-card'
	limit?: number; // 允许上传文件的最大数量
	multiple?: boolean; // 是否支持多选文件
	uploadTip?: string; // 文件提示
	headers?: Headers | Record<string, any>; // 设置上传的请求头部
	method?: string; // 设置上传请求方法 默认post
	data?: Record<string, any>; // 上传时附带的额外参数
	name?: string; // 上传的文件字段名 默认file
	formParam: { [key: string]: any }; // 提交参数
	column: FromBoxProps;
	action?: string;
	size?: number; // 单个文件限制的大小，默认5MB
	fileType?: FileTypes[]; // 图片类型限制 ==> 非必传（默认为 ["image/jpeg", "image/png", "image/gif"]）
	disabled?: boolean; // 是否禁用上传, 默认true
	changeForm?: (file: any) => void;
}
const dialogImageUrl = ref('');
const dialogVisible = ref(false);
// 是否还能上传文件
const isShowUpIcon = ref(true);
// 传参
const props = withDefaults(defineProps<Upload>(), {
	listType: 'text',
	limit: 10,
	size: 5,
	headers: () => {
		return {
			token: GlobalStore().userToken
		};
	},
	multiple: true,
	fileType: () => ['image/jpeg', 'image/png', 'image/gif', 'image/jpg'],
	changeForm: () => {}
});
const accept = props.fileType.join(',');

/**
 * 删除文件
 * @param file
 * @param uploadFiles
 */
const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
	console.log(file, uploadFiles);
	changeUpload();
};

/**
 * 文件预览
 * @param uploadFile
 */
const handlePreview: UploadProps['onPreview'] = uploadFile => {
	console.log(JSON.stringify(uploadFile));
	if (props.listType === 'text') {
		return;
	}
	dialogImageUrl.value = uploadFile.url!;
	dialogVisible.value = true;
};

/**
 * 当超出限制时，执行的钩子函数
 * @param files
 */
const handleExceed: UploadProps['onExceed'] = files => {
	ElMessage.warning(`只允许上传${props.limit}个文件, 当前上传${files.length}文件`);
};
// 设置是否触发beforeRemove方法状态
let isBeforeRemove = true;
const beforeRemove: UploadProps['beforeRemove'] = uploadFile => {
	return isBeforeRemove
		? ElMessageBox.confirm(`确定删除${uploadFile.name ?? '该图片'}吗 ?`).then(
				() => true,
				() => false
		  )
		: true;
};
// 上传文件之前的钩子，参数为上传的文件， 若返回false或者返回 Promise 且被 reject，则停止上传。
const beforeUpload: UploadProps['beforeUpload'] = rawFile => {
	isBeforeRemove = true;
	const typeName = rawFile.name.substring(rawFile.name.lastIndexOf('.') + 1);
	const imgType = ['jpeg', 'png', 'jpg', 'gif', 'bmp', 'pjpeg', 'apng'];

	// 上传的是图片类型校验
	if (props.listType !== 'text' && !props.fileType.includes(rawFile.type as FileTypes) && !props.fileType.includes('image/*')) {
		ElMessage.error('上传图片不符合所需的格式');
		isBeforeRemove = false;
		return false;
	} else if (
		// 校验所有文件类型
		props.listType === 'text' &&
		!props.fileType.includes(imgType.includes(typeName) ? (`image/${typeName}` as FileTypes) : (`.${typeName}` as FileTypes))
	) {
		ElMessage.error('上传图片不符合所需的格式1');
		isBeforeRemove = false;
		return false;
	} else if (rawFile.size / 1024 / 1024 > props.size) {
		ElMessage.error(`上传的文件不能超过${props.size}MB!`);
		isBeforeRemove = false;
		return false;
	}
	return true;
};
/**
 * 上传文件成功回调
 * @param response
 * @param uploadFile
 */
const handleSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
	changeUpload();
	if (typeof props.changeForm === 'function') {
		props.changeForm(uploadFile);
	}
};
/**
 * 是否展示上传按钮
 */
const changeUpload = () => {
	if (props.formParam[props.column!.prop].length >= props.limit) {
		isShowUpIcon.value = false;
	} else {
		isShowUpIcon.value = true;
	}
};
</script>

<style lang="scss" scoped>
.j-upload-file {
	width: 100%;
	&.disabled:deep(.el-upload--text) {
		display: none;
	}
	&.disabled:deep(.el-upload--picture-card) {
		display: none;
	}
	:deep(.el-dialog__body img) {
		width: 100%;
	}
}
</style>
